#ifndef TASK_QUEUE_H
#define TASK_QUEUE_H

#include <queue>
#include <optional>
#include <memory>
#include "Task.h"

namespace TaskManage
{
    template<typename T>
    class TaskQueue
    {
    public:
        [[nodiscard]] inline int GetSize()
        {
            if (queueUpdated)
            {
                size = tQueue.size();
                for (auto &i : tqQueue)
                    size += i.GetSize();
                queueUpdated = false;
            }
            return size;
        }

        std::optional<std::shared_ptr<Task < T>>>

        GetNext()
        {
            std::optional<std::shared_ptr<Task<T>>> result = std::nullopt;
            do
            {
                if (typeQueue.front() == QItemType::task)
                {
                    if (typeQueue.empty())
                    {
                        result = std::nullopt;
                        break;
                    }
                    result = tQueue.front();
                    typeQueue.pop();
                    tQueue.pop();
                    break;
                }
                if (typeQueue.front() == QItemType::queue)
                {
                    auto innerResult = (tqQueue.front())->GetNext();
                    if (innerResult.has_value())
                    {
                        result = innerResult.value();
                        break;
                    }
                    typeQueue.pop();
                    tqQueue.pop();
                    result = GetNext();
                    break;
                }
            } while (false);
            return result;
        }

        inline void Append(std::shared_ptr<Task < T>>

        task)
        {
            typeQueue.push(QItemType::task);
            tQueue.push(task);
            queueUpdated = true;
        }

        void Append(std::shared_ptr<TaskQueue<T>> taskQueue)
        {
            typeQueue.push(QItemType::queue);
            tqQueue.push(taskQueue);
            queueUpdated = true;
        }

    private:
        enum QItemType : uint8_t
        {
            task = 0,
            queue = 1
        };
        std::queue<QItemType> typeQueue;
        std::queue<std::shared_ptr<Task < T>>>
        tQueue;
        std::queue<std::shared_ptr<TaskQueue<T>>> tqQueue;

        int size = 0;
        bool queueUpdated = true;
    };
}

#endif //TASK_QUEUE_H
